package cn.edu.zafu.camera.manager;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.util.Log;
import android.view.SurfaceHolder;

import com.tms.app.tms.app.MyApp;
import com.tms.app.tms.utils.SharePreferenceUtil;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;

/**
 * User:lizhangqu(513163535@qq.com)
 * Date:2015-09-05
 * Time: 10:56
 */
public class CameraManager2 implements Camera.AutoFocusCallback,Camera.PreviewCallback{
    private static final String TAG = CameraManager2.class.getName();
    private Camera camera;
    private Camera.Parameters parameters;
    private AutoFocusManager2 autoFocusManager;
    private int requestedCameraId = -1;
    private boolean isShibie=false;

    private boolean initialized;
    private boolean previewing;


    private static final long AUTO_FOCUS_INTERVAL_MS = 2000L;
    private static final Collection<String> FOCUS_MODES_CALLING_AF;
    static {
        FOCUS_MODES_CALLING_AF = new ArrayList<String>(2);
        FOCUS_MODES_CALLING_AF.add(Camera.Parameters.FOCUS_MODE_AUTO);
        FOCUS_MODES_CALLING_AF.add(Camera.Parameters.FOCUS_MODE_MACRO);
    }

    private boolean stopped;
    private boolean focusing;
    private  boolean useAutoFocus=true;
    private AsyncTask<?,?,?> outstandingTask;


    /**
     * 打开摄像头
     *
     * @param cameraId 摄像头id
     * @return Camera
     */
    public Camera open(int cameraId) {
        int numCameras = Camera.getNumberOfCameras();
        if (numCameras == 0) {
            Log.e(TAG, "No cameras!");
            return null;
        }
        boolean explicitRequest = cameraId >= 0;
        if (!explicitRequest) {
            // Select a camera if no explicit camera requested
            int index = 0;
            while (index < numCameras) {
                Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
                Camera.getCameraInfo(index, cameraInfo);
                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                    break;
                }
                index++;
            }
            cameraId = index;
        }
        Camera camera;
        if (cameraId < numCameras) {
            Log.e(TAG, "Opening camera #" + cameraId);
            camera = Camera.open(cameraId);
        } else {
            if (explicitRequest) {
                Log.e(TAG, "Requested camera does not exist: " + cameraId);
                camera = null;
            } else {
                Log.e(TAG, "No camera facing back; returning camera #0");
                camera = Camera.open(0);
            }
        }
        return camera;
    }

    /**
     * 打开camera
     *
     * @param holder SurfaceHolder
     * @throws IOException IOException
     */
    public synchronized void openDriver(SurfaceHolder holder)
            throws IOException {
        Log.e(TAG, "openDriver");
        Camera theCamera = camera;
        if (theCamera == null) {
            theCamera = open(requestedCameraId);
            if (theCamera == null) {
                throw new IOException();
            }
            camera = theCamera;
        }
        theCamera.setPreviewDisplay(holder);

        if (!initialized) {
            initialized = true;
            parameters = camera.getParameters();
            List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();

            int w = 800;
            int h = 600;
            for (Camera.Size size : previewSizes) {
                Log.e("TAG", "previewSizes width:" + size.width);
                Log.e("TAG", "previewSizes height:" + size.height);
                if (size.width - w <= 100) {
                    w = size.width;
                    h = size.height;
                    break;
                }
            }

            parameters.setPreviewSize(w, h);
            parameters.setPictureFormat(ImageFormat.JPEG);
            parameters.setJpegQuality(100);
            int w2 = 0;
            int h2 = 0;

            for (Camera.Size size : parameters.getSupportedPictureSizes()) {
              if (size.width>size.height)
              {
                  if (size.width>=800&&size.width<2000){
                      w2 = size.width;
                      h2 = size.height;
                      break;
                  }
              }
            }
            if (parameters.getSupportedPictureSizes().size()==1)
            {
                w2=parameters.getSupportedPictureSizes().get(0).width;
                h2=parameters.getSupportedPictureSizes().get(0).height;
            }
          //  parameters.setPictureSize(800, 600);// p10.mete10 注释调此行
            if (w2!=0)
            {
                if (!SharePreferenceUtil.getBoolean(MyApp.getInstance().getApplicationContext(),"isEMUI",true))
                {
                      parameters.setPictureSize(w2, h2);// p10.mete10 注释调此行
                }
            }
            theCamera.setParameters(parameters);
            theCamera.setPreviewCallback(this);
        }
    }

    /**
     * camera是否打开
     *
     * @return camera是否打开
     */
    public synchronized boolean isOpen() {
        return camera != null;
    }

    /**
     * 关闭camera
     */
    public synchronized void closeDriver() {
        Log.e(TAG, "closeDriver");
        if (camera != null) {
            camera.setPreviewCallback(null);
            camera.release();
            camera = null;
        }
    }

    /**
     * 开始预览
     */
    public synchronized void startPreview() {
        Log.e(TAG, "startPreview");
        Camera theCamera = camera;
        if (theCamera != null && !previewing) {
            theCamera.startPreview();
            previewing = true;
//            if (autoFocusManager==null)
//                autoFocusManager = new AutoFocusManager2(camera,focused);
            String currentFocusMode = camera.getParameters().getFocusMode();
            useAutoFocus = FOCUS_MODES_CALLING_AF.contains(currentFocusMode);
            start();
        }
    }

    /**
     * 关闭预览
     */
    public synchronized void stopPreview() {
        Log.e(TAG, "stopPreview");
        if (autoFocusManager != null) {
            autoFocusManager.stop();
            autoFocusManager = null;
        }
        if (camera != null && previewing) {
            camera.stopPreview();
            previewing = false;
        }
    }

    /**
     * 打开闪光灯
     */
    public synchronized void openLight() {
        Log.e(TAG, "openLight");
        if (camera != null) {
            parameters = camera.getParameters();
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
            camera.setParameters(parameters);
        }
    }

    /**
     * 打开设置缩放
     */
    public synchronized void setZoom(int pregress) {
        Log.e(TAG, "openLight");
        if (camera != null) {
            parameters = camera.getParameters();
//            if (!parameters.isSmoothZoomSupported())
//                return;
            int maxZoom = parameters.getMaxZoom();
            int zoom=parameters.getZoom();
            //   parameters.setZoom((int) (pregress * 1.0f / (maxZoom * 100) * maxZoom));

            if (zoom+pregress>maxZoom){
                zoom=maxZoom;
            }
            else if (zoom+pregress<0){
                zoom=0;
            }
           else{
                zoom=zoom+pregress;
            }
            if (zoom==parameters.getZoom())
                return;
            parameters.setZoom(zoom);
            camera.setParameters(parameters);
        }
    }

    /**
     * 关闭闪光灯
     */
    public synchronized void offLight() {
        Log.e(TAG, "offLight");
        if (camera != null) {
            parameters = camera.getParameters();
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            camera.setParameters(parameters);
        }
    }

    /**
     * 拍照
     *
     * @param shutter ShutterCallback
     * @param raw     PictureCallback
     * @param jpeg    PictureCallback
     */
    public synchronized void takePicture(final Camera.ShutterCallback shutter, final Camera.PictureCallback raw,
                                         final Camera.PictureCallback jpeg) {

        camera.takePicture(shutter, raw, jpeg);
       // startPreview();


    }

    @Override
    public void onAutoFocus(boolean success, Camera camera) {
        focusing = false;
        autoFocusAgainLater();
    }

    /**
     * 开始自动对焦
     */
    public synchronized void start() {
        if (useAutoFocus) {
            outstandingTask = null;
            if (!stopped && !focusing) {
                try {
                    if (camera!=null)
                        camera.autoFocus(this);
                    focusing = true;
                } catch (RuntimeException re) {
                    // Have heard RuntimeException reported in Android 4.0.x+; continue?
                    Log.e(TAG, "Unexpected exception while focusing", re);
                    // Try again later to keep cycle going
                    autoFocusAgainLater();
                }
            }
        }
    }

    private synchronized void autoFocusAgainLater() {
        if (!stopped && outstandingTask == null) {
            AutoFocusTask newTask = new AutoFocusTask();
            try {
                newTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                outstandingTask = newTask;
            } catch (RejectedExecutionException ree) {
                Log.e(TAG, "Could not request auto focus", ree);
            }
        }
    }


    private synchronized void cancelOutstandingTask() {
        if (outstandingTask != null) {
            if (outstandingTask.getStatus() != AsyncTask.Status.FINISHED) {
                outstandingTask.cancel(true);
            }
            outstandingTask = null;
        }
    }

    /**
     * 停止自动对焦
     */
    public synchronized void stop() {
        stopped = true;
        if (useAutoFocus) {
            cancelOutstandingTask();
            // Doesn't hurt to call this even if not focusing
            try {
                camera.cancelAutoFocus();
            } catch (RuntimeException re) {
                // Have heard RuntimeException reported in Android 4.0.x+; continue?
                Log.e(TAG, "Unexpected exception while cancelling focusing", re);
            }
        }
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera sCamera) {
        if (data==null)
            return;
        if (!isShibie){
            if (focusing)
                return;
        }
            Camera.Size previewSize = sCamera.getParameters().getPreviewSize();
            YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            yuvImage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 80, baos);
            byte[] jdata = baos.toByteArray();
            Bitmap tmpBitmap = BitmapFactory.decodeByteArray( jdata, 0, jdata.length);
            if(tmpBitmap!=null) {
                saveBitmapToSDCard(tmpBitmap,"原图");
                Bitmap mRvcBitmap = Bitmap.createScaledBitmap(tmpBitmap, 400, 180, false);
                if(!mRvcBitmap.equals(tmpBitmap)) {
                    tmpBitmap.recycle();
                    tmpBitmap = null;
                }
                saveBitmapToSDCard(mRvcBitmap,"切图");
               // camera.startPreview();
            } else {
               // Log("tmpBitmap is null" + sCamera.getParameters().getPictureFormat());
            }
    }




    private final class AutoFocusTask extends AsyncTask<Object,Object,Object> {
        @Override
        protected Object doInBackground(Object... voids) {
            try {
                Thread.sleep(AUTO_FOCUS_INTERVAL_MS);
            } catch (InterruptedException e) {
                // continue
            }
            start();
            return null;
        }
    }

    /**
     * 保存bitmap到SD卡
     * @param bitmap
     * @param imagename
     */
    public static String saveBitmapToSDCard(Bitmap bitmap, String imagename) {
        String path = "/sdcard/" + "img-" + imagename + ".jpg";
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(path);
            if (fos != null) {
                bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
                fos.close();
            }

            return path;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
